package cn.iocoder.yudao.module.system.controller.admin.teacherdashboard.vo;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;

/**
 * 教师看板分页请求 VO
 * 支持分页和懒加载，优化大数据量场景下的性能
 *
 * @author 芋道源码
 */
@Schema(description = "管理后台 - 教师看板分页请求 VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class TeacherDashboardPageReqVO extends TeacherDashboardReqVO {

    // ==================== 分页参数 ====================

    @Schema(description = "页码，从1开始", example = "1")
    @Min(value = 1, message = "页码必须大于0")
    private Integer pageNo = 1;

    @Schema(description = "每页条数", example = "20")
    @Min(value = 1, message = "每页条数必须大于0")
    @Max(value = 500, message = "每页条数不能超过500")
    private Integer pageSize = 20;

    // ==================== 懒加载控制参数 ====================

    @Schema(description = "是否加载所有学生数据（默认false，使用分页）", example = "false")
    private Boolean loadAllStudents = false;

    @Schema(description = "学生排名加载数量（0表示不加载）", example = "50")
    @Min(value = 0, message = "学生排名加载数量不能小于0")
    @Max(value = 1000, message = "学生排名加载数量不能超过1000")
    private Integer studentRankingLimit = 50;

    @Schema(description = "重点关注学生加载数量（0表示不加载）", example = "20")
    @Min(value = 0, message = "重点关注学生数量不能小于0")
    @Max(value = 100, message = "重点关注学生数量不能超过100")
    private Integer focusStudentLimit = 20;

    @Schema(description = "教学建议加载数量（0表示不加载）", example = "10")
    @Min(value = 0, message = "教学建议数量不能小于0")
    @Max(value = 50, message = "教学建议数量不能超过50")
    private Integer teachingSuggestionLimit = 10;

    // ==================== 数据加载级别控制 ====================

    @Schema(description = "数据加载级别：BASIC(基础), STANDARD(标准), FULL(完整)", example = "STANDARD")
    private DataLoadLevel loadLevel = DataLoadLevel.STANDARD;

    @Schema(description = "是否启用缓存（默认true）", example = "true")
    private Boolean enableCache = true;

    @Schema(description = "是否异步加载非关键数据（默认true）", example = "true")
    private Boolean enableAsyncLoad = true;

    @Schema(description = "缓存过期时间（分钟，0表示使用默认值）", example = "30")
    @Min(value = 0, message = "缓存过期时间不能小于0")
    @Max(value = 1440, message = "缓存过期时间不能超过1440分钟")
    private Integer cacheExpireMinutes = 0;

    // ==================== 排序参数 ====================

    @Schema(description = "学生排序字段：TOTAL_SCORE(总分), CLASS_RANK(班级排名), GRADE_RANK(年级排名)", example = "TOTAL_SCORE")
    private StudentSortField studentSortField = StudentSortField.TOTAL_SCORE;

    @Schema(description = "排序方向：ASC(升序), DESC(降序)", example = "DESC")
    private SortDirection sortDirection = SortDirection.DESC;

    // ==================== 过滤参数 ====================

    @Schema(description = "最低总分过滤（0表示不过滤）", example = "0")
    @Min(value = 0, message = "最低总分不能小于0")
    private Integer minTotalScore = 0;

    @Schema(description = "最高总分过滤（0表示不过滤）", example = "0")
    @Min(value = 0, message = "最高总分不能小于0")
    private Integer maxTotalScore = 0;

    @Schema(description = "选科组合过滤", example = "物理+化学+生物")
    private String subjectCombination;

    @Schema(description = "学生姓名模糊查询", example = "张三")
    private String studentNameLike;

    // ==================== 枚举定义 ====================

    /**
     * 数据加载级别
     */
    public enum DataLoadLevel {
        /**
         * 基础级别：只加载班级信息和考试概况
         */
        BASIC,
        
        /**
         * 标准级别：加载基础数据 + 成绩统计 + 学生排名（分页）
         */
        STANDARD,
        
        /**
         * 完整级别：加载所有数据（适用于数据导出等场景）
         */
        FULL
    }

    /**
     * 学生排序字段
     */
    public enum StudentSortField {
        /**
         * 按总分排序
         */
        TOTAL_SCORE,
        
        /**
         * 按班级排名排序
         */
        CLASS_RANK,
        
        /**
         * 按年级排名排序
         */
        GRADE_RANK,
        
        /**
         * 按学号排序
         */
        STUDENT_NO,
        
        /**
         * 按姓名排序
         */
        STUDENT_NAME
    }

    /**
     * 排序方向
     */
    public enum SortDirection {
        /**
         * 升序
         */
        ASC,
        
        /**
         * 降序
         */
        DESC
    }

    // ==================== 便利方法 ====================

    /**
     * 获取分页偏移量
     */
    public Integer getOffset() {
        return (pageNo - 1) * pageSize;
    }

    /**
     * 是否需要分页
     */
    public Boolean needPagination() {
        return !Boolean.TRUE.equals(loadAllStudents) && loadLevel != DataLoadLevel.FULL;
    }

    /**
     * 是否需要加载学生排名
     */
    public Boolean needStudentRanking() {
        return studentRankingLimit != null && studentRankingLimit > 0;
    }

    /**
     * 是否需要加载重点关注学生
     */
    public Boolean needFocusStudents() {
        return focusStudentLimit != null && focusStudentLimit > 0;
    }

    /**
     * 是否需要加载教学建议
     */
    public Boolean needTeachingSuggestions() {
        return teachingSuggestionLimit != null && teachingSuggestionLimit > 0;
    }

    /**
     * 是否启用总分过滤
     */
    public Boolean hasTotalScoreFilter() {
        return (minTotalScore != null && minTotalScore > 0) || 
               (maxTotalScore != null && maxTotalScore > 0);
    }

    /**
     * 是否启用选科组合过滤
     */
    public Boolean hasSubjectCombinationFilter() {
        return subjectCombination != null && !subjectCombination.trim().isEmpty();
    }

    /**
     * 是否启用学生姓名过滤
     */
    public Boolean hasStudentNameFilter() {
        return studentNameLike != null && !studentNameLike.trim().isEmpty();
    }

    /**
     * 获取实际的学生排名限制数量
     */
    public Integer getActualStudentRankingLimit() {
        if (!needStudentRanking()) {
            return 0;
        }
        
        // 根据加载级别调整限制数量
        switch (loadLevel) {
            case BASIC:
                return Math.min(studentRankingLimit, 10);
            case STANDARD:
                return Math.min(studentRankingLimit, 50);
            case FULL:
                return studentRankingLimit;
            default:
                return studentRankingLimit;
        }
    }

    /**
     * 获取实际的重点关注学生限制数量
     */
    public Integer getActualFocusStudentLimit() {
        if (!needFocusStudents()) {
            return 0;
        }
        
        // 根据加载级别调整限制数量
        switch (loadLevel) {
            case BASIC:
                return Math.min(focusStudentLimit, 5);
            case STANDARD:
                return Math.min(focusStudentLimit, 20);
            case FULL:
                return focusStudentLimit;
            default:
                return focusStudentLimit;
        }
    }

    /**
     * 获取实际的教学建议限制数量
     */
    public Integer getActualTeachingSuggestionLimit() {
        if (!needTeachingSuggestions()) {
            return 0;
        }
        
        // 根据加载级别调整限制数量
        switch (loadLevel) {
            case BASIC:
                return Math.min(teachingSuggestionLimit, 3);
            case STANDARD:
                return Math.min(teachingSuggestionLimit, 10);
            case FULL:
                return teachingSuggestionLimit;
            default:
                return teachingSuggestionLimit;
        }
    }

    /**
     * 生成缓存键的一部分
     */
    public String toCacheKeyPart() {
        StringBuilder sb = new StringBuilder();
        sb.append("page:").append(pageNo);
        sb.append(":size:").append(pageSize);
        sb.append(":level:").append(loadLevel.name());
        sb.append(":sort:").append(studentSortField.name()).append(":").append(sortDirection.name());
        
        if (hasTotalScoreFilter()) {
            sb.append(":score:").append(minTotalScore).append("-").append(maxTotalScore);
        }
        
        if (hasSubjectCombinationFilter()) {
            sb.append(":subject:").append(subjectCombination.hashCode());
        }
        
        if (hasStudentNameFilter()) {
            sb.append(":name:").append(studentNameLike.hashCode());
        }
        
        return sb.toString();
    }
}